using System;
using System.Collections.Generic;
using UnityEngine;

namespace NL.Advanced
{

    public class Blockers
    {
        public List<Blocker> Items = new List<Blocker>();


        public bool Blocking
        {
            get
            {
                if (Items == null || Items.Count == 0) return false;

                foreach (var b in Items)
                {
                    if (b.Blocking)
                        return true;
                }
                return false;
            }
        }

        public void Excute(Action on)
        {
            if (Blocking) return;

            on?.Invoke();
        }
    }
    public class Blocker : MonoBehaviour
    {

        [SerializeField] bool _Blocking;

        public bool Blocking => _Blocking;

        static Dictionary<string, Blocker> _ALL = new Dictionary<string, Blocker>();
        public static Blocker GET(string name)
        {
            return _ALL.ContainsKey(name) ? _ALL[name] : _CREATE(name);
        }
        public static bool HasBlocking(string name)
        {
            return _ALL.ContainsKey(name) ? _ALL[name].Blocking : false;
        }
        public static Blockers GET(params string[] names)
        {
            Blockers all = new Blockers();

            foreach (string name in names)
            {
                if (!string.IsNullOrEmpty(name) && _ALL.ContainsKey(name))
                    all.Items.Add(_ALL[name]);
            }
            return all;
        }

        static Blocker _CREATE(string name)
        {
            return new GameObject(name).AddComponent<Blocker>();
        }
        private void Awake()
        {
            if (!_ALL.ContainsKey(name))
                _ALL.Add(name, this);
        }
        private void OnDestroy()
        {
            _ALL.Remove(name);
        }
        List<GameObject> _Owners = new List<GameObject>();
        public Blocker Open(GameObject who = null)
        {
            _Blocking = true;
            if (who != null && !_Owners.Contains(who))
            {
                _Owners.Add(who);
            }

            LOG.Add($"Blocker start name:{name} who:{who?.name} count:{_Owners.Count}");
            return this;
        }
        public Blocker Close(GameObject who = null)
        {
            if (who != null)
            {
                _Owners.Remove(who);
                if (_Owners.Count == 0)
                    _DoClose();
            }
            else
            {
                _DoClose();
            }

            LOG.Add($"Blocker close name:{name} who:{who?.name} count:{_Owners.Count}");

            return this;
        }

        void _DoClose()
        {
            LOG.Add($"Blocker closed name:{name}");
            _Blocking = false;
            Invoke("DoBlockClose", 0.02f);
        }


        List<Action> _AllActions = new List<Action>();
        void DoBlockClose()
        {
            foreach (var a in _AllActions)
            {
                try
                {
                    a.Invoke();
                }
                catch (Exception e)
                {
                    Debug.LogError($"[Blocker.DoBlockClose]:{e.Message}");
                }
            }
            _AllActions.Clear();
        }
        /// <summary>
        /// 等待堵塞因子,并且执行; 相同委托只会被添加一次.
        /// </summary>
        /// <param name="on"></param>
        /// <param name="onlyexcute">是否仅仅执行,不回等待委托. </param>
        public void WaitOrExcute(Action on, bool onlyexcute = false)
        {
            if (!_Blocking)
            {
                on?.Invoke();
            }
            else
            {
                if (!onlyexcute)
                {
                    if (_AllActions.Count >= 1)
                    {
                        LOG.Add("...");
                    }
                    foreach (var a in _AllActions)
                    {
                        if (a.Method.MethodHandle == on.Method.MethodHandle)
                        {
                            LOG.Add($"[Blocker.WaitOrExcute]: SameAction....");
                            return;
                        }
                    }
                    _AllActions.Add(on);
                }
            }
        }

    }


    public static class BlockerEX
    {
        public static void Add()
        {
            Blocker b;

            // if(b._Blocking)
            {

            }
        }
    }

}
